import 'dart:math';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:umeng_apm_sdk/umeng_apm_sdk.dart';

import 'package:palette_generator/palette_generator.dart';
import 'package:ball_lion/module/pick/ai/ai_type.dart';
import 'package:ball_lion/service/resource_service.dart';
import 'package:ball_lion/entity/other/resource_entity.dart';
import 'package:ball_lion/resources/styles.dart';
import 'package:ball_lion/resources/colours.dart';
import 'package:ball_lion/utils/utils.dart';
import 'package:ball_lion/widgets/base/wqs_text.dart';

typedef BannerRefreshBuilder = Widget Function(ScrollPhysics physics);

class BannerLogic extends GetxController {
  List<ResourceEntity> carousel = [];
  final _num = (-1.0).obs;
  final ScrollController scrollController = ApmScrollController();
  Color color = Colours.transparent;
  final _offset = 0.0.obs;

  double get num {
    if (_num < 0) {
      return 0.0;
    } else if (_num > 1) {
      return 1.0;
    } else {
      return _num.value;
    }
  }

  double get offset {
    if (_offset < 0) {
      return 0.0;
    } else if (_offset > 1) {
      return 1.0;
    } else {
      return _offset.value;
    }
  }

  set offset(value) {
    _offset.value = value;
    update();
  }

  set num(value) {
    _num.value = value;
    update();
  }

  Future getData(String type) async {
    carousel = [];
    Get.find<ResourceService>().lbt.forEach((element) {
      if (element.button == type) {
        carousel.add(element);
      }
    });
    if (carousel.isNotEmpty) {
      await PaletteGenerator.fromImageProvider(
              NetworkImage(carousel[0].imgUrl ?? ""),
              size: Size(Get.width, 168),
              region: Rect.fromLTWH(Get.width - 20, 0, 20, 20))
          .then((value) {
        return color =
            value.colors.toList()[Random().nextInt(value.colors.length)];
      });
    }
    update();
  }
}

class BannerScaffold extends StatelessWidget {
  BannerScaffold(
      {super.key,
      required this.type,
      required this.body,
      this.bannerHeight = 214,
      this.needAppBar = true,
      this.aboveWidget,
      this.needScroll = false,
      this.titleFade = false,
      this.backFade = true,
      this.title,
      this.action = const [],
      this.titleWidget,
      this.bodyTopWidget,
      this.refreshController,
      this.scrollController,
      this.onRefresh,
      this.onLoad,
      this.picPadding,
      this.picDecoration,
      this.picOverLay = 12,
      this.backColor,
      this.fadeColor,
      this.cornerFade = false,
      this.aboveFade = false,
      this.brightness});

  final String type;
  final bool needScroll;
  final double bannerHeight;
  final bool needAppBar;
  final Widget? aboveWidget;
  final Widget? bodyTopWidget;
  final bool titleFade;
  final bool backFade;
  final bool aboveFade;
  final Color? fadeColor;
  final String? title;
  final Widget? titleWidget;
  final Color? backColor;
  final bool cornerFade;
  final Brightness? brightness;
  final EasyRefreshController? refreshController;
  final ScrollController? scrollController;
  final Function()? onRefresh;
  final Function()? onLoad;
  final EdgeInsets? picPadding;
  final BoxDecoration? picDecoration;
  final double picOverLay;
  final List<Widget> action;
  final BannerRefreshBuilder body;
  late final BannerLogic logic = Get.put(BannerLogic(), tag: type);

  @override
  Widget build(BuildContext context) {
    return GetBuilder<BannerLogic>(
        tag: type,
        initState: (state) {
          logic.getData(type);
          if (scrollController == null) {
            logic.scrollController.addListener(() {
              logic.offset = logic.scrollController.offset;
              if (backFade || titleFade) {
                logic.num = logic.scrollController.offset /
                    logic.scrollController.position.maxScrollExtent;
              }
            });
          } else {
            scrollController!.addListener(() {
              if (backFade || titleFade) {
                logic.num = scrollController!.offset /
                    scrollController!.position.maxScrollExtent;
              }
            });
          }
        },
        builder: (logic) {
          return Container(
            height: Get.height,
            color: backColor ?? Colours.white,
            child: Stack(
              children: [
                Positioned(
                    top: 0,
                    left: 0,
                    right: 0,
                    child: Column(
                      children: [
                        Container(
                          clipBehavior: picDecoration != null
                              ? Clip.antiAlias
                              : Clip.none,
                          margin: picPadding ?? EdgeInsets.zero,
                          decoration: picDecoration,
                          child: CachedNetworkImage(
                            width: Get.width,
                            height: picDecoration != null ? bannerHeight : null,
                            fit: BoxFit.cover,
                            imageUrl: logic.carousel.hasValue
                                ? logic.carousel[0].imgUrl?.trim() ?? ""
                                : "",
                            errorWidget: (context, url, error) => Container(),
                            placeholder: (context, url) => Container(),
                          ),
                        ),
                      ],
                    )),
                EasyRefresh.builder(
                  controller: refreshController,
                  scrollController: scrollController ?? logic.scrollController,
                  onRefresh: onRefresh,
                  onLoad: onLoad,
                  header: Styles.refreshHeader(
                      position: IndicatorPosition.locator, clamping: true),
                  footer:
                      Styles.refreshFooter(position: IndicatorPosition.locator),
                  childBuilder: (BuildContext context, ScrollPhysics physics) =>
                      ExtendedNestedScrollView(
                          controller:
                              scrollController ?? logic.scrollController,
                          onlyOneScrollInBody: true,
                          physics: needScroll
                              ? physics
                              : const NeverScrollableScrollPhysics(),
                          pinnedHeaderSliverHeightBuilder: () => needScroll
                              ? (needAppBar ? 44 : 0) +
                                  MediaQuery.of(context).padding.top
                              : bannerHeight - picOverLay,
                          headerSliverBuilder: (context, innerBoxIsScrolled) =>
                              [
                                Obx(() => SliverAppBar(
                                      title: titleWidget ??
                                          QsText(title ??
                                              AiType.getTypeByTag(type)?.name ??
                                              ""),
                                      backgroundColor: fadeColor != null
                                          ? fadeColor?.withOpacity(
                                              backFade ? logic.num : 0)
                                          : logic.color.withOpacity(
                                              backFade ? logic.num : 0),
                                      systemOverlayStyle: SystemUiOverlayStyle(
                                          statusBarIconBrightness: brightness),
                                      titleTextStyle: TextStyle(
                                          fontSize: 20,
                                          color: Colours.white.withOpacity(
                                              titleFade ? logic.num : 1)),
                                      toolbarHeight: 44,
                                      actions: action,
                                      leading: needAppBar
                                          ? IconButton(
                                              onPressed: Get.back,
                                              icon: Image.asset(
                                                  Utils.getImgPath(
                                                      'arrow_back.png'),
                                                  width: 24,
                                                  height: 24,
                                                  color: Colours.white),
                                            )
                                          : Container(),
                                      collapsedHeight: 44,
                                      expandedHeight: bannerHeight -
                                          MediaQuery.of(context).padding.top -
                                          picOverLay,
                                      flexibleSpace: FlexibleSpaceBar(
                                        collapseMode: CollapseMode.none,
                                        background: Container(
                                            clipBehavior: Clip.antiAlias,
                                            decoration: const BoxDecoration(),
                                            foregroundDecoration: BoxDecoration(
                                                color: fadeColor != null
                                                    ? fadeColor?.withOpacity(
                                                        backFade
                                                            ? logic.num
                                                            : 0)
                                                    : logic.color.withOpacity(
                                                        backFade
                                                            ? logic.num
                                                            : 0)),
                                            child: Opacity(
                                                opacity: 1 -
                                                    (aboveFade
                                                        ? logic.num
                                                        : logic.num * 0),
                                                child: aboveWidget ??
                                                    Container())),
                                      ),
                                    ))
                              ],
                          body: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              bodyTopWidget ?? Container(),
                              Expanded(
                                child: Obx(() => Container(
                                    clipBehavior: Clip.antiAlias,
                                    decoration: BoxDecoration(
                                        color: Colours.greyF2F3F7,
                                        borderRadius: BorderRadius.vertical(
                                            top: Radius.circular(
                                                (picDecoration != null
                                                        ? 0
                                                        : 8) *
                                                    (1 -
                                                        (cornerFade
                                                            ? logic.num / 1
                                                            : logic.num *
                                                                0))))),
                                    child: body(physics))),
                              ),
                            ],
                          )),
                ),
              ],
            ),
          );
        });
  }
}
